#include <sys_config.h>
#include <types.h>
#include <basic_types.h>
#include <osal/osal.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <hld/smc/smc.h>

#include <api/libcas/mcas_ca_info.h>
#include "mcas_card.h"

//#define CARD_DEBUG
#ifdef MCAS_DEBUG
#define CARD_DEBUG_PRINTF	libc_printf
#define CARD_DEBUG_DUMP(data,len) { const int l=(len); int i;\
                         for(i=0 ; i<l ; i++) CARD_DEBUG_PRINTF(" 0x%02x",*((data)+i)); \
                         CARD_DEBUG_PRINTF("\n"); }
#else
#define CARD_DEBUG_PRINTF(...)	do{}while(0)
#define CARD_DEBUG_DUMP(data,len) ;
#endif



static mcas_card_t mcas_sc[MCAS_CARD_MAX_NUM];

BOOL mcas_card_exist()
{
	UINT8 i;
	
	for(i=0;i<MCAS_CARD_MAX_NUM;i++)
	{
		if(mcas_sc[i].dev != NULL)
		{
			if(smc_card_exist(mcas_sc[i].dev)==SUCCESS)
				return TRUE;
		}
	}
	return FALSE;
}

void mcas_card_get_info(struct smc_device *smc_dev, mcas_card_t *card_info)
{
	UINT8 i;
	
	for(i=0;i<MCAS_CARD_MAX_NUM;i++)
	{
		if(mcas_sc[i].dev == smc_dev)
		{
			MEMCPY(card_info, &mcas_sc[i], sizeof(mcas_card_t));
			return;	
		}
	}

	MEMSET(card_info, 0, sizeof(mcas_card_t));

}


struct smc_device * mcas_card_match(UINT8 * ca_desc_data, UINT8 *card_inited)
{
	UINT8 i;
	struct smc_device *dev = NULL;
	UINT16 ca_system_id = ((ca_desc_data[2]<<8)|ca_desc_data[3]);
	
	for(i=0;i<MCAS_CARD_MAX_NUM;i++)
	{
		if(mcas_sc[i].ca_system_id == ca_system_id)
		{
			if(mcas_sc[i].dev != NULL)
			{	
				dev = mcas_sc[i].dev;
				*card_inited = mcas_sc[i].inited;
				break;
			}
		}
	}

	return dev;
}


static INT32 mcas_card_init(UINT8 index, struct smc_device *smc_dev, UINT8 *atr,
	UINT8 atr_len, UINT16 *ca_system_id)
{
	INT32 ret = SUCCESS;
	INT32 i;
	UINT16 system_id = 0;
		
	MEMSET(&mcas_sc[index], 0, sizeof(mcas_card_t));
	
	if((index>=MCAS_CARD_MAX_NUM)||(smc_dev==NULL)||(atr==NULL)||(atr_len==0))
	{
		CARD_DEBUG_PRINTF("mcas_sc_init: param error\n");
		return !SUCCESS;
	}
	/*here init card of each system
	if()
	{
		system_id = CAS_SYS_CONAX;
		ret = conax_init(smc_dev, atr, atr_len);
	}
	else if()
	{
		system_id = CAS_SYS_IRDETO;
		ret = irdeto_init(smc_dev, atr, atr_len);
		
	}
	else if()
	{
		system_id = CAS_SYS_SECA;
		ret = seca_init(smc_dev, atr, atr_len);
	}
	else if()
	{
		system_id = CAS_SYS_VIACCESS;	
		ret = viaccess_init(smc_dev, atr, atr_len);
	}
	else
	{
		CARD_DEBUG_PRINTF("mcas_sc_init: unknow card\n");
		return !SUCCESS;
	}
	*/
	
	if(SUCCESS == ret)
	{
		mcas_sc[index].dev =smc_dev;
		mcas_sc[index].ca_system_id = system_id;
		mcas_sc[index].inited = 1;
		
		/*here config the decoder, update clear functions for each system
		switch(system_id)
		{
			case CAS_SYS_CONAX:
				mcas_sc[index].sc_decoder = conax_decoder;
				mcas_sc[index].sc_update = conax_update;
				mcas_sc[index].sc_clear = conax_clear;
				
				break;
			case CAS_SYS_BETA:
				mcas_sc[index].sc_decoder = beta_decoder;
				mcas_sc[index].sc_update = brta_update;
				mcas_sc[index].sc_clear = beta_clear;
				
				break;
			case CAS_SYS_IRDETO:
				mcas_sc[index].sc_decoder = irdeto_decoder;
				mcas_sc[index].sc_update = irdeto_update;
				mcas_sc[index].sc_clear = irdeto_clear;
				
				break;
			case CAS_SYS_NAG1:
				mcas_sc[index].sc_decoder = nag1_decoder;
				mcas_sc[index].sc_update = nag1_update;
				mcas_sc[index].sc_clear = nag1_clear;
				
				break;
			case CAS_SYS_NAG2:
				mcas_sc[index].sc_decoder = nag2_decoder;
				mcas_sc[index].sc_update = nag2_update;
				mcas_sc[index].sc_clear = nag2_clear;
				
				break;
			case CAS_SYS_SECA:
				mcas_sc[index].sc_decoder = seca_decoder;
				mcas_sc[index].sc_update = seca_update;
				mcas_sc[index].sc_clear = seca_clear;
				
				break;
			case CAS_SYS_VIACCESS:
				mcas_sc[index].sc_decoder = viaccess_decoder;
				mcas_sc[index].sc_update = viaccess_update;
				mcas_sc[index].sc_clear = viaccess_clear;
				
				break;
		}
		*/
	}
	
	*ca_system_id =system_id;
	
	return ret;
}



INT32 mcas_card_in(UINT8 index, struct smc_device *smc_dev, UINT16 *ca_system_id)
{
	INT32 ret;
	UINT8 buffer[33];
	UINT16 atr_size;
		
	ret = smc_reset(smc_dev, buffer, &atr_size);
	if(ret != RET_SUCCESS)
	{
		CARD_DEBUG_PRINTF("cas_smc_inserted: mute card\n");
		return ret;
	}
	if(SUCCESS == mcas_card_init(index, smc_dev, buffer, atr_size,ca_system_id))
	{
				
		return SUCCESS;
	}
	else
		return !SUCCESS;
}


BOOL mcas_card_out(struct smc_device *smc_dev)
{
	BOOL ret=FALSE;
	UINT8 i;
	
	if(smc_dev==NULL)
	{
		CARD_DEBUG_PRINTF("mcas_sc_clear: param error\n");
		return FALSE;
	}
	for(i=0;i<MCAS_CARD_MAX_NUM;i++)
	{
		if(mcas_sc[i].dev == smc_dev)
		{
			if(mcas_sc[i].sc_clear != NULL)
			{
				ret = mcas_sc[i].sc_clear();
				mcas_sc[i].sc_clear = NULL;
			}
			else
			{
				CARD_DEBUG_PRINTF("mcas_sc_clear: no ca system handler\n");
			}
			MEMSET(&mcas_sc[i], 0, sizeof(mcas_card_t));
			
			break;
		}
	}
	
	return ret;
}


BOOL mcas_card_decoder(struct smc_device *smc_dev, UINT8 *ecm_data, UINT16 data_len,UINT8 *cw)
{
	BOOL ret = FALSE;
	UINT8 i;
	
	if((smc_dev==NULL)||(ecm_data==0))
	{
		CARD_DEBUG_PRINTF("mcas_sc_decoder: param error\n");
		return FALSE;
	}
	for(i=0;i<MCAS_CARD_MAX_NUM;i++)
	{
		if(mcas_sc[i].dev==smc_dev)
		{
			if(mcas_sc[i].sc_decoder != NULL)
				ret = mcas_sc[i].sc_decoder(smc_dev,ecm_data,data_len,cw);
			else
				CARD_DEBUG_PRINTF("mcas_sc_clear: no ca system handler error\n");
		}
	}
	return ret;
}

BOOL mcas_card_update(struct smc_device *smc_dev, UINT8 *emm_data, UINT16 data_len)
{
	BOOL ret = FALSE;
	UINT8 i;
	
	if((smc_dev==NULL)||(emm_data==0))
	{
		CARD_DEBUG_PRINTF("mcas_sc_update: param error\n");
		return FALSE;
	}
	for(i=0;i<MCAS_CARD_MAX_NUM;i++)
	{
		if(mcas_sc[i].dev==smc_dev)
		{
			if(mcas_sc[i].sc_update != NULL)
				ret = mcas_sc[i].sc_update(smc_dev,emm_data,data_len);
			else
				CARD_DEBUG_PRINTF("mcas_sc_update: no ca system handler error\n");
		}
	}
	return ret;
}



